home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / spatial / rots.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  12.7 KB  |  524 lines

  1. /* (C) Copyright 1991 Andrew Plotkin. Permission is
  2.  given to copy and use, as long as this copyright
  3.  notice is retained. */
  4.  
  5. #include <stdio.h>
  6. #include <math.h>    
  7. #include <X11/Xlib.h>
  8. #include "spatial.h"
  9.  
  10. typedef struct _cubep {
  11.     int x, y, z;
  12. } cubep;
  13.  
  14. point plist[MAXPOINTS];        /* shape, arbitrarily rotated */
  15. point traplist[MAXPOINTS];  /* plist + offsets */
  16. point templist[MAXCUBES];   /* temporary version */
  17. double offx, offy, offz;
  18. double focallen, boardscale;
  19. int halfboard, halfboard2;
  20. fieldplist fieldpts;
  21. fieldplist fieldpts2;
  22.  
  23. int colors[11] = {1, 3, 4, 7, 9, 10, 11, 12, 13, 14, 15};
  24.  
  25. extern GC gcblack, gcwhite, gcinv, gccopy, gcline, gccubes[]; 
  26.  
  27. extern void updatepiece(), setup_fieldpm();
  28. extern void add_one_cubie(), update_meter();
  29.  
  30. void startpiece()
  31. {
  32.     piecelist *p;
  33.     register int ix;
  34.     int res;
  35.     double flix, fliy, fliz;
  36.  
  37.     curpiece = random() % numpieces;
  38.     flix = (random()%2)*2-1;
  39.     fliy = (random()%2)*2-1;
  40.     fliz = (random()%2)*2-1;
  41.  
  42.     p = &(pieces[curpiece]);
  43.     for (ix=0; ix<p->numpoints; ix++) {
  44.     plist[ix].x = flix*p->points[ix].x;
  45.     plist[ix].y = fliy*p->points[ix].y;
  46.     plist[ix].z = fliz*p->points[ix].z;
  47.     plist[ix].w = p->points[ix].w;
  48.     traplist[ix].w = plist[ix].w;
  49.     };
  50.     offx=0.0;
  51.     offy=0.0;
  52.     offz=(double)fieldz+5.0;
  53.     updatepiece();
  54.     res = collision(0);
  55.     while (res>=1 && res<=6) {
  56.     switch (res) {
  57.         case 1:
  58.         offz = floor(offz - 1.0 + 0.5);
  59.         break;
  60.         case 2:
  61.         fprintf(stderr,
  62.             "spatial: piece too long for board\n");
  63.         exit(-1);
  64.         break;
  65.         case 3:
  66.         offy = floor(offy + 1.0 + 0.5);
  67.         break;
  68.         case 4:
  69.         offy = floor(offy - 1.0 + 0.5);
  70.         break;
  71.         case 5:
  72.         offx = floor(offx - 1.0 + 0.5);
  73.         break;
  74.         case 6:
  75.         offx = floor(offx + 1.0 + 0.5);
  76.         break;
  77.     }
  78.     updatepiece();
  79.     res = collision(0);
  80.     };
  81.     if (res==(-1)) curpiece = (-2);
  82. }
  83.  
  84. void rotate_piece(axis, theta) /* works on plist */
  85. int axis;
  86. double theta;
  87. {
  88.     register int ix;
  89.     double t1, t2;
  90.     double sinth = sin(theta);
  91.     double costh = cos(theta);
  92.  
  93.     switch (axis) {
  94.     case 1:
  95.         for (ix=0; ix<pieces[curpiece].numpoints; ix++) {
  96.         t1 = plist[ix].y;
  97.         t2 = plist[ix].z;
  98.         plist[ix].y = costh*t1 - sinth*t2;
  99.         plist[ix].z = sinth*t1 + costh*t2;
  100.         }
  101.         break;
  102.     case 2:
  103.         for (ix=0; ix<pieces[curpiece].numpoints; ix++) {
  104.         t1 = plist[ix].x;
  105.         t2 = plist[ix].z;
  106.         plist[ix].x = costh*t1 - sinth*t2;
  107.         plist[ix].z = sinth*t1 + costh*t2;
  108.         }
  109.         break;
  110.     case 3:
  111.         for (ix=0; ix<pieces[curpiece].numpoints; ix++) {
  112.         t1 = plist[ix].x;
  113.         t2 = plist[ix].y;
  114.         plist[ix].x = costh*t1 - sinth*t2;
  115.         plist[ix].y = sinth*t1 + costh*t2;
  116.         }
  117.         break;
  118.     }
  119. }
  120.  
  121. void updatepiece() /* create traplist from plist+offsets */
  122. {
  123.     register int ix;
  124.  
  125.     for (ix=0; ix<pieces[curpiece].numpoints; ix++) {
  126.     traplist[ix].x = plist[ix].x + offx;
  127.     traplist[ix].y = plist[ix].y + offy;
  128.     traplist[ix].z = plist[ix].z + offz;
  129.     };
  130. }
  131.  
  132. void updatetemp_tra(xa, ya, za, taxi, tdir)
  133. short xa, ya, za, taxi, tdir;
  134. {
  135.     register int ix;
  136.  
  137.     switch (taxi) {
  138.     case 0:
  139.         for (ix=0; ix<pieces[curpiece].numcubes; ix++) {
  140.         templist[ix].x = traplist[ix].x;
  141.         templist[ix].y = traplist[ix].y;
  142.         templist[ix].z = traplist[ix].z;
  143.         };
  144.         break;
  145.     case 1:
  146.         for (ix=0; ix<pieces[curpiece].numcubes; ix++) {
  147.         templist[ix].x = plist[ix].x + offx;
  148.         templist[ix].y = -tdir*plist[ix].z + offy;
  149.         templist[ix].z = tdir*plist[ix].y + offz;
  150.         };
  151.         break;
  152.     case 2:
  153.         for (ix=0; ix<pieces[curpiece].numcubes; ix++) {
  154.         templist[ix].x = -tdir*plist[ix].z + offx;
  155.         templist[ix].y = plist[ix].y + offy;
  156.         templist[ix].z = tdir*plist[ix].x + offz;
  157.         };
  158.         break;
  159.     case 3:
  160.         for (ix=0; ix<pieces[curpiece].numcubes; ix++) {
  161.         templist[ix].x = -tdir*plist[ix].y + offx;
  162.         templist[ix].y = tdir*plist[ix].x + offy;
  163.         templist[ix].z = plist[ix].z + offz;
  164.         };
  165.         break;
  166.     }
  167.  
  168.     for (ix=0; ix<pieces[curpiece].numcubes; ix++) {
  169.     templist[ix].x += (double)xa;
  170.     templist[ix].y += (double)ya;
  171.     templist[ix].z += (double)za;
  172.     };
  173. }
  174.  
  175. void round_piece() /* round off piece to int
  176.  offsets, halfint coords */
  177. {
  178.     register int ix;
  179.  
  180.     offx = floor(offx+0.5);
  181.     offy = floor(offy+0.5);
  182.     offz = floor(offz+0.5);
  183.  
  184.     for (ix=0; ix<pieces[curpiece].numpoints; ix++) {
  185.     plist[ix].x = floor(2.0*plist[ix].x + 0.5)/2.0;
  186.     plist[ix].y = floor(2.0*plist[ix].y + 0.5)/2.0;
  187.     plist[ix].z = floor(2.0*plist[ix].z + 0.5)/2.0;
  188.     };
  189. }
  190.  
  191. int collision(listflag)
  192. /* returns (in this priority)
  193.  1: out-of-field up;
  194.  2: ...down;
  195.  3: ...north;
  196.  4: ...south;
  197.  5: ...east;
  198.  6: ...west;
  199.  -1 for cube overlap; 
  200.  0 for ok; 
  201.  */
  202. int listflag;
  203. {
  204.     register int ix;
  205.     cubep cubes[MAXCUBES];
  206.     point *pls;
  207.  
  208.     if (listflag==0) pls = traplist;
  209.     else pls = templist;
  210.  
  211.     for (ix=0; ix<pieces[curpiece].numcubes; ix++) {
  212.     cubes[ix].x = (int)(pls[ix].x+100.0) - 100;
  213.     cubes[ix].y = (int)(pls[ix].y+100.0) - 100;
  214.     cubes[ix].z = (int)(pls[ix].z+100.0) - 100;
  215.  
  216.     if (cubes[ix].z < 0) return 2;
  217.     if (cubes[ix].z >= fieldz) return 1;
  218.     if (cubes[ix].y < 0) return 3;
  219.     if (cubes[ix].y >= fieldy) return 4;
  220.     if (cubes[ix].x >= fieldx) return 5;
  221.     if (cubes[ix].x < 0) return 6;
  222.     };
  223.     for (ix=0; ix<pieces[curpiece].numcubes; ix++) {
  224.     if (field[cubes[ix].x][cubes[ix].y][cubes[ix].z] & F_ON)
  225.         return (-1);
  226.     };
  227.     return 0;
  228. }
  229.  
  230. void setup_cubies()
  231. {
  232.     register int ix, iy, iz;
  233.     double wcoord;
  234.  
  235.     for (ix=0; ix<=fieldx; ix++)
  236.     for (iy=0; iy<=fieldy; iy++)
  237.         for (iz=0; iz<=fieldz; iz++) {
  238.         wcoord = -((double)iz+fieldoffz)/focallen + 1.0;
  239.         fieldpts[ix][iy][iz].x = halfboard +
  240.           (int)(boardscale*((double)ix+fieldoffx)/wcoord);
  241.         fieldpts[ix][iy][iz].y = halfboard +
  242.           (int)(boardscale*((double)iy+fieldoffy)/wcoord);
  243.         }
  244.  
  245.     if (stereo) {
  246.     for (ix=0; ix<=fieldx; ix++)
  247.         for (iy=0; iy<=fieldy; iy++)
  248.         for (iz=0; iz<=fieldz; iz++) {
  249.             wcoord = -((double)iz+fieldoffz)/focallen + 1.0;
  250.             fieldpts2[ix][iy][iz].x = halfboard2 +
  251.               (int)(boardscale*((double)ix+fieldoffx2) / wcoord);
  252.             fieldpts2[ix][iy][iz].y = halfboard +
  253.               (int)(boardscale*((double)iy+fieldoffy) / wcoord);
  254.         }
  255.     }
  256. }
  257.  
  258. void add_cubie(cx, cy, cz)
  259. int cx, cy, cz;
  260. {
  261.     add_one_cubie(fieldpts, cx, cy, cz);
  262.     if (stereo)
  263.     add_one_cubie(fieldpts2, cx, cy, cz);
  264. }
  265.  
  266. void add_one_cubie(fips, cx, cy, cz)
  267. fieldplist fips;
  268. int cx, cy, cz;
  269. {
  270.     int x1, y1, width, heigh;
  271.     XPoint face[5];
  272.     GC *gcc;
  273.  
  274.     gcc = &(gccubes[colors[cz]]);
  275.     x1 = fips[cx][cy][cz+1].x;
  276.     y1 = fips[cx][cy][cz+1].y;
  277.     width = fips[cx+1][cy+1][cz+1].x - x1 + 1;
  278.     heigh = fips[cx+1][cy+1][cz+1].y - y1 + 1;
  279.     XFillRectangle(dpy, fieldpm, *gcc, x1, y1, width, heigh);
  280.     XDrawRectangle(dpy, fieldpm, gcwhite, x1, y1, width, heigh);
  281.  
  282.     x1 = cx - fieldx/2;
  283.     if (x1<0) {
  284.     face[0].x = fips[cx+1][cy][cz+1].x;
  285.     face[0].y = fips[cx+1][cy][cz+1].y;
  286.     face[1].x = fips[cx+1][cy][cz].x;
  287.     face[1].y = fips[cx+1][cy][cz].y;
  288.     face[2].x = fips[cx+1][cy+1][cz].x;
  289.     face[2].y = fips[cx+1][cy+1][cz].y;
  290.     face[3].x = fips[cx+1][cy+1][cz+1].x;
  291.     face[3].y = fips[cx+1][cy+1][cz+1].y;
  292.     face[4].x = face[0].x;
  293.     face[4].y = face[0].y;
  294.     XFillPolygon(dpy, fieldpm, *gcc, face, 4,
  295.              Convex, CoordModeOrigin);
  296.     XDrawLines(dpy, fieldpm, gcwhite, face, 5,
  297.            CoordModeOrigin);
  298.     }
  299.     else if (x1>0) {
  300.     face[0].x = fips[cx][cy][cz+1].x;
  301.     face[0].y = fips[cx][cy][cz+1].y;
  302.     face[1].x = fips[cx][cy][cz].x;
  303.     face[1].y = fips[cx][cy][cz].y;
  304.     face[2].x = fips[cx][cy+1][cz].x;
  305.     face[2].y = fips[cx][cy+1][cz].y;
  306.     face[3].x = fips[cx][cy+1][cz+1].x;
  307.     face[3].y = fips[cx][cy+1][cz+1].y;
  308.     face[4].x = face[0].x;
  309.     face[4].y = face[0].y;
  310.     XFillPolygon(dpy, fieldpm, *gcc, face, 4,
  311.              Convex, CoordModeOrigin);
  312.     XDrawLines(dpy, fieldpm, gcwhite, face, 5,
  313.            CoordModeOrigin);
  314.     };
  315.  
  316.     y1 = cy - fieldy/2;
  317.     if (y1>0) {
  318.     face[0].x = fips[cx][cy][cz+1].x;
  319.     face[0].y = fips[cx][cy][cz+1].y;
  320.     face[1].x = fips[cx][cy][cz].x;
  321.     face[1].y = fips[cx][cy][cz].y;
  322.     face[2].x = fips[cx+1][cy][cz].x;
  323.     face[2].y = fips[cx+1][cy][cz].y;
  324.     face[3].x = fips[cx+1][cy][cz+1].x;
  325.     face[3].y = fips[cx+1][cy][cz+1].y;
  326.     face[4].x = face[0].x;
  327.     face[4].y = face[0].y;
  328.     XFillPolygon(dpy, fieldpm, *gcc, face, 4,
  329.              Convex, CoordModeOrigin);
  330.     XDrawLines(dpy, fieldpm, gcwhite, face, 5,
  331.            CoordModeOrigin);
  332.     }
  333.     else if (y1<0) {
  334.     face[0].x = fips[cx][cy+1][cz+1].x;
  335.     face[0].y = fips[cx][cy+1][cz+1].y;
  336.     face[1].x = fips[cx][cy+1][cz].x;
  337.     face[1].y = fips[cx][cy+1][cz].y;
  338.     face[2].x = fips[cx+1][cy+1][cz].x;
  339.     face[2].y = fips[cx+1][cy+1][cz].y;
  340.     face[3].x = fips[cx+1][cy+1][cz+1].x;
  341.     face[3].y = fips[cx+1][cy+1][cz+1].y;
  342.     face[4].x = face[0].x;
  343.     face[4].y = face[0].y;
  344.     XFillPolygon(dpy, fieldpm, *gcc, face, 4,
  345.              Convex, CoordModeOrigin);
  346.     XDrawLines(dpy, fieldpm, gcwhite, face, 5,
  347.            CoordModeOrigin);
  348.     };
  349. }
  350.  
  351. void add_cubies(lev)
  352. int lev;
  353. {
  354.     register int ix, iy, iz;
  355.  
  356.     for (iz=lev; iz<fieldz; iz++) {
  357.     for (ix=0; ix<fieldx/2; ix++) {
  358.         for (iy=0; iy<fieldy/2; iy++) {
  359.         if (field[ix][iy][iz] & F_ON) {
  360.             add_cubie(ix, iy, iz);
  361.         }
  362.         }
  363.         for (iy=fieldy-1; iy>=fieldy/2; iy--) {        
  364.         if (field[ix][iy][iz] & F_ON) {
  365.             add_cubie(ix, iy, iz);
  366.         }
  367.         }
  368.     }
  369.     for (ix=fieldx-1; ix>=fieldx/2; ix--) {
  370.         for (iy=0; iy<fieldy/2; iy++) {
  371.         if (field[ix][iy][iz] & F_ON) {
  372.             add_cubie(ix, iy, iz);
  373.         }
  374.         }
  375.         for (iy=fieldy-1; iy>=fieldy/2; iy--) {
  376.         if (field[ix][iy][iz] & F_ON) {
  377.             add_cubie(ix, iy, iz);
  378.         }
  379.         }
  380.     }
  381.     };
  382.     if (meterlev != meteroldlev) {
  383.     update_meter();
  384.     }
  385. }
  386.  
  387. void redraw_cubies()
  388. {
  389.     register int ix, iy, iz;
  390.  
  391.     for (iz=0; iz<fieldz; iz++) {
  392.     for (ix=0; ix<fieldx/2; ix++) {
  393.         for (iy=0; iy<fieldy/2; iy++) {
  394.         if (field[ix][iy][iz] & F_ON) {
  395.             add_cubie(ix, iy, iz);
  396.         }
  397.         }
  398.         for (iy=fieldy-1; iy>=fieldy/2; iy--) {        
  399.         if (field[ix][iy][iz] & F_ON) {
  400.             add_cubie(ix, iy, iz);
  401.         }
  402.         }
  403.     }
  404.     for (ix=fieldx-1; ix>=fieldx/2; ix--) {
  405.         for (iy=0; iy<fieldy/2; iy++) {
  406.         if (field[ix][iy][iz] & F_ON) {
  407.             add_cubie(ix, iy, iz);
  408.         }
  409.         }
  410.         for (iy=fieldy-1; iy>=fieldy/2; iy--) {
  411.         if (field[ix][iy][iz] & F_ON) {
  412.             add_cubie(ix, iy, iz);
  413.         }
  414.         }
  415.     }
  416.     }
  417.     if (meterlev != meteroldlev) {
  418.     update_meter();
  419.     }
  420. }
  421.  
  422. void plop_piece()
  423. {
  424.     register int ix, iy, iz;
  425.     int cubx, cuby, cubz;
  426.     int dirx, diry;
  427.     int lev = fieldz+1;
  428.  
  429.     for (ix=0; ix<pieces[curpiece].numcubes; ix++) {
  430.     cubx = (int)(traplist[ix].x+100.0) - 100;
  431.     cuby = (int)(traplist[ix].y+100.0) - 100;
  432.     cubz = (int)(traplist[ix].z+100.0) - 100;
  433.     if (cubz < lev) lev = cubz;
  434.     if (cubz+1 > meterlev) meterlev = cubz+1;
  435.     field[cubx][cuby][cubz] |= F_ON;
  436.     };
  437.     add_cubies(lev);
  438.  
  439.     /* settle */
  440.     while (1) {
  441.     int full;
  442.     for (iz=fieldz-1; iz>=0; iz--) {
  443.         full=1;
  444.         for (ix=0; full && (ix<fieldx); ix++) {
  445.         for (iy=0; full && (iy<fieldy); iy++) {
  446.             if (!(field[ix][iy][iz] & F_ON)) full = 0;
  447.         }
  448.         }
  449.         if (full) break;
  450.     }
  451.     if (iz<0) break;
  452.     for (; iz<fieldz-1; iz++) 
  453.         for (ix=0; ix<fieldx; ix++)
  454.         for (iy=0; iy<fieldy; iy++)
  455.             field[ix][iy][iz] = field[ix][iy][iz+1];
  456.     for (ix=0; ix<fieldx; ix++)
  457.         for (iy=0; iy<fieldy; iy++)
  458.         field[ix][iy][fieldz-1] = 0;
  459.     score += 20*fieldx*fieldy;
  460.     if (dropticks > 10) dropticks -= 6;
  461.     meterlev--;
  462.     setup_fieldpm();
  463.     redraw_cubies();
  464.     }
  465. }
  466.  
  467. void draw_curpiece(drw)
  468. Drawable drw;
  469. {
  470.     register int ix;
  471.     static point scoor[MAXVERTS];
  472.     static point scoor2[MAXVERTS];
  473.     static XSegment xpl[MAXEDGES*2];
  474.     double wcoord;
  475.     int poff = pieces[curpiece].numcubes;
  476.     int nume = pieces[curpiece].numedges;
  477.     edge *e = pieces[curpiece].edges;
  478.  
  479.     shapex1 = dispx;
  480.     shapex2 = 0;
  481.     shapey1 = dispy;
  482.     shapey2 = 0;
  483.     for (ix=0; ix<pieces[curpiece].numverts; ix++) {
  484.     wcoord = -(traplist[ix+poff].z+fieldoffz)/focallen + 1.0;
  485.     scoor[ix].x = halfboard +
  486.       (int)(boardscale*(traplist[ix+poff].x+fieldoffx)/wcoord);
  487.     scoor[ix].y = halfboard +
  488.       (int)(boardscale*(traplist[ix+poff].y+fieldoffy)/wcoord);
  489.     if (shapex1>scoor[ix].x-1) shapex1=scoor[ix].x-1;
  490.     if (shapey1>scoor[ix].y-1) shapey1=scoor[ix].y-1;
  491.     if (shapex2<scoor[ix].x+1) shapex2=scoor[ix].x+1;
  492.     if (shapey2<scoor[ix].y+1) shapey2=scoor[ix].y+1;
  493.     if (stereo) {
  494.         scoor2[ix].x = halfboard2 +
  495.           (int)(boardscale*(traplist[ix+poff].x+fieldoffx2)
  496.             / wcoord);
  497.         if (shapex2<scoor2[ix].x+1) shapex2=scoor2[ix].x+1;
  498.     }
  499.     }
  500.  
  501.     if (!stereo) {
  502.     for (ix=0; ix<nume; ix++) {
  503.         xpl[ix].x1 = scoor[e[ix].head].x;
  504.         xpl[ix].y1 = scoor[e[ix].head].y;
  505.         xpl[ix].x2 = scoor[e[ix].tail].x;
  506.         xpl[ix].y2 = scoor[e[ix].tail].y;
  507.     }
  508.     XDrawSegments(dpy, drw, gcline, xpl, nume);
  509.     }
  510.     else {
  511.     for (ix=0; ix<nume; ix++) {
  512.         xpl[ix].x1 = scoor[e[ix].head].x;
  513.         xpl[ix].y1 = scoor[e[ix].head].y;
  514.         xpl[ix].x2 = scoor[e[ix].tail].x;
  515.         xpl[ix].y2 = scoor[e[ix].tail].y;
  516.         xpl[nume+ix].x1 = scoor2[e[ix].head].x;
  517.         xpl[nume+ix].y1 = xpl[ix].y1;
  518.         xpl[nume+ix].x2 = scoor2[e[ix].tail].x;
  519.         xpl[nume+ix].y2 = xpl[ix].y2;
  520.     }
  521.     XDrawSegments(dpy, drw, gcline, xpl, 2*nume);
  522.     }
  523. }
  524.